//
// Created by Administrator on 2023/3/16.
//

#include "socket.h"
#include "unistd.h"
#include "sys/socket.h"
#include "arpa/inet.h"
#include "log/logger_main.h"

socket::socket(int fd) : fd(fd) {}

socket::~socket() {
    close();
}

void socket::close() {
    ::close(fd);
    this->fd = -1;
}

void socket::bind(int16_t port) {

    struct sockaddr_in sockaddrIn;

    sockaddrIn.sin_family = AF_INET;
    sockaddrIn.sin_port = htons(port);
//    sockaddrIn.sin_addr.s_addr= inet_addr(ip.data());//转换为网络字节序
    sockaddrIn.sin_addr.s_addr = htonl(INADDR_ANY);//转换为网络字节序
    if (::bind(fd, (sockaddr *) &sockaddrIn, sizeof(sockaddrIn)) < 0)
        LOG_ERROR("bind error");

}

void socket::listen() {

    if (::listen(fd, SOMAXCONN) < 0)
        LOG_ERROR("listen error");

}

void socket::set_reused(bool p) {
    int opt = p;
    if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt,
                     static_cast<socklen_t>(sizeof opt))) {

        LOG_ERROR("set_reused({}) error fd={}", p, fd);
    }

    if (::setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &opt,
                     static_cast<socklen_t>(sizeof opt))) {

        LOG_ERROR("set_reused_port({}) error fd={}", p, fd);
    }


}

class socket socket::accept(int listen) {
    struct sockaddr_in out;
    socklen_t len = sizeof(out);
    //4这个函数直接设置非阻塞以及 fork自动关闭
    auto ret = accept4(listen, (sockaddr *) &out, &len, SOCK_NONBLOCK | SOCK_CLOEXEC);
    auto remote_addr = inet_ntoa(out.sin_addr);
    socket res(ret);


    static int count = 0;
    LOG_INFO("连接总数{}", std::to_string(++count));

    res.remote_ip = remote_addr;
    return res;

}


class socket &socket::operator=(socket &&other) {
    if (this == &other)
        return *this;
    this->close();
    this->fd = other.fd;
    other.fd = -1;
    this->remote_ip = std::move(other.remote_ip);
    return *this;
}

socket::socket(socket &&s) {
    this->fd = s.fd;
    s.fd = -1;
    this->remote_ip = std::move(s.remote_ip);
}

const int socket::get_fd() {
    return this->fd;
}

socket::socket() {}

const std::string &socket::getRemoteIp() const {
    return remote_ip;
}

void socket::setRemoteIp(const std::string &remoteIp) {
    remote_ip = remoteIp;
}

